package com.yidu.ladder.aspect;  
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.yidu.ladder.system.domain.Log;
import com.yidu.ladder.system.domain.User;
import com.yidu.ladder.system.service.LogService;  
/**
 * 日志监控类
 * @author bamboo
 *
 */
@Aspect
@Component
public class LogAspect {  
    /**
     * 用户id
     */
    public String id=null;   
    /**
     * 用户名字
     */
    public String name=null;  
    
    @Autowired  
    LogService logService;  
      
    
    public LogService getLogService() {
		return logService;
	}

	public void setLogService(LogService logService) {
		this.logService = logService;
	}

	/** 
     * 管理员登录方法的切入点 
     */  
    @Pointcut("execution(* com.yidu.ladder.system.controller.*.login(..))")  
    public void loginCell(){  
    }  
      
    /** 
     * 添加业务逻辑方法切入点 
     */  
    @Pointcut("execution(* com.yidu.ladder.*.service.*.save*(..))")  
    public void insertCell() {  
    }  
  
    /** 
     * 修改业务逻辑方法切入点 
     */  
    @Pointcut("execution(* com.yidu.ladder.*.service.*.update*(..))")  
    public void updateCell() {  
    }  
  
    /** 
     * 删除业务逻辑方法切入点 
     */  
    @Pointcut("execution(* com.yidu.ladder.*.service.*.frozenOrRecove*(..))")  
    public void deleteCell() {  
    }  
      
    
    /** 
     * 登录操作(后置通知) 
     * @param joinPoint 
     * @param object 
     * @throws Throwable 
     */  
    @AfterReturning(value = "loginCell()", returning = "object")  
    public void loginLog(JoinPoint joinPoint, Map<String, Object> object) throws Throwable {  
    	//获取请求
    	HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    	//用户对象
    	User user =(User)object.get("user");
    	// 获取方法名  
        String methodName = joinPoint.getSignature().getName();  
        System.out.println("执行方法"+methodName);
        //判断用户
        if (user==null) {  
        	Log log = new Log();  
            log.setOperateResult("N");  
            String clientIp = getClientIp(request);
            log.setHost(clientIp);
            log.setOperateTime(new Date()); 
            log.setUserName("游客");
            log.setOperateType("登录"); 
            log.setOperateEvent(methodName); 
            logService.addLog(log);  
            return;  
        }  
        
        if (joinPoint.getArgs() == null) {// 没有参数  
            return;  
            
        }  
        //得到用户Id
        id=user.getUserId(); 
        //得到用户名
        name=user.getUserName();
        //创建日志对象
        Log log = new Log();  
        String clientIp = getClientIp(request);
        log.setHost(clientIp);
        log.setUserId(user.getUserId());  
        log.setUserName(user.getUserName());
        log.setOperateTime(new Date()); 
        log.setOperateEvent(methodName); 
        log.setOperateType("登录");
        log.setOperateResult("Y");  
        logService.addLog(log);  
    }  
      
    /** 
     * 添加操作日志(后置通知) 
     *  
     * @param joinPoint 
     * @param object 
     */  
    @AfterReturning(value = "insertCell()", argNames = "object", returning = "object")  
    public void insertLog(JoinPoint joinPoint, Object object) throws Throwable {  
        // Admin admin=(Admin)  
        // request.getSession().getAttribute("businessAdmin");  
    	HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    	// 获取方法名  
        String methodName = joinPoint.getSignature().getName();  
        // 获取操作内容  
        //String opContent = optionContent(joinPoint.getArgs(), methodName); 
    	// 判断参数  
        if (joinPoint.getArgs() == null) {// 没有参数  
        	Log log = new Log();   
            String clientIp = getClientIp(request);
            log.setHost(clientIp);
            log.setUserId(id);  
            log.setUserName(name);
            log.setOperateTime(new Date()); 
            log.setOperateType("添加"); 
            log.setOperateEvent(methodName);
            log.setOperateResult("N"); 
            logService.addLog(log); 
            return;  
        }  
        //添加日志
        Log log = new Log();   
        String clientIp = getClientIp(request);
        log.setHost(clientIp);
        log.setUserId(id);  
        log.setUserName(name);
        log.setOperateTime(new Date()); 
        log.setOperateType("添加"); 
        log.setOperateEvent(methodName);
        log.setOperateResult("Y"); 
        logService.addLog(log);  
    }  
  
    /** 
     * 管理员修改操作日志(后置通知) 
     *  
     * @param joinPoint 连接点
     * @param object 对象
     * @throws Throwable 异常
     */  
    @AfterReturning(value = "updateCell()", argNames = "object", returning = "object")  
    public void updateLog(JoinPoint joinPoint, Object object) throws Throwable {  
        // Admin admin=(Admin)  
        // request.getSession().getAttribute("businessAdmin");  
    	HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    	// 获取方法名  
        String methodName = joinPoint.getSignature().getName();  
        // 获取操作内容  
        //String opContent = optionContent(joinPoint.getArgs(), methodName); 
    	// 判断参数  
        if (joinPoint.getArgs() == null) {// 没有参数  
        	Log log = new Log();   
            String clientIp = getClientIp(request);
            log.setHost(clientIp);
            log.setUserId(id);  
            log.setUserName(name);
            log.setOperateTime(new Date()); 
            log.setOperateType("修改"); 
            log.setOperateEvent(methodName);
            log.setOperateResult("N"); 
            logService.addLog(log);
            return;  
        }  
        
        Log log = new Log();   
        String clientIp = getClientIp(request);
        log.setHost(clientIp);
        log.setUserId(id);  
        log.setUserName(name);
        log.setOperateTime(new Date()); 
        log.setOperateType("修改"); 
        log.setOperateEvent(methodName);
        log.setOperateResult("Y"); 
        logService.addLog(log); 
    }  
  
    /** 
     * 删除操作 
     *  
     * @param joinPoint 
     * @param object 
     */  
    @AfterReturning(value = "deleteCell()", argNames = "object", returning = "object")  
    public void deleteLog(JoinPoint joinPoint, Object object) throws Throwable {  
        // Admin admin=(Admin)  
        // request.getSession().getAttribute("businessAdmin");  
    	//http请求对象
    	HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    	// 判断参数  
        if (joinPoint.getArgs() == null) {// 没有参数  
            return;  
        }  
        // 获取方法名  
        String methodName = joinPoint.getSignature().getName();  
        
        StringBuffer rs = new StringBuffer();  
        rs.append(methodName);  
        String className = null;  
        for (Object info : joinPoint.getArgs()) {  
            // 获取对象类型  
            className = info.getClass().getName();  
            className = className.substring(className.lastIndexOf(".") + 1);  
            rs.append("[参数，类型:" + className + "，值:(id:"  
                    + joinPoint.getArgs()[0] + ")");  
        }  
  
        Log log = new Log();   
        String clientIp = getClientIp(request);
        log.setHost(clientIp);
        log.setUserId(id);  
        log.setUserName(name);
        log.setOperateTime(new Date()); 
        log.setOperateType("状态修改"); 
        log.setOperateEvent(methodName);
        log.setOperateResult("Y"); 
        logService.addLog(log);  
    }  
  
    /** 
     * 使用Java反射来获取被拦截方法(insert、update)的参数值， 将参数值拼接为操作内容 
     *  
     * @param args 
     * @param mName 
     * @return 
     */  
    public String optionContent(Object[] args, String mName) {  
        if (args == null) {  
            return null;  
        }  
        StringBuffer rs = new StringBuffer();  
        rs.append(mName);  
        String className = null;  
        int index = 1;  
        // 遍历参数对象  
        for (Object info : args) {  
            // 获取对象类型  
            className = info.getClass().getName();  
            className = className.substring(className.lastIndexOf(".") + 1);  
            rs.append("[参数" + index + "，类型:" + className + "，值:");  
            // 获取对象的所有方法  
            Method[] methods = info.getClass().getDeclaredMethods();  
            // 遍历方法，判断get方法  
            for (Method method : methods) {  
                String methodName = method.getName();  
                // 判断是不是get方法  
                if (methodName.indexOf("get") == -1) {// 不是get方法  
                    continue;// 不处理  
                }  
                Object rsValue = null;  
                try {  
                    // 调用get方法，获取返回值  
                    rsValue = method.invoke(info);  
                } catch (Exception e) {  
                    continue;  
                }  
                // 将值加入内容中  
                rs.append("(" + methodName + ":" + rsValue + ")");  
            }  
            rs.append("]");  
            index++;  
        }  
        return rs.toString();  
    }  
    
    /**
     * 获取用户真实IP地址，不使用request.getRemoteAddr();的原因是有可能用户使用了代理软件方式避免真实IP地址。
     * 可是，如果通过了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP值，究竟哪个才是真正的用户端的真实IP呢？ 
     * 答案是取X-Forwarded-For中第一个非unknown的有效IP字符串
     * @param request
     * @return
     */
    public String getClientIp(HttpServletRequest request) {
        String ipAddress = null;
        ipAddress = request.getHeader("x-forwarded-for");
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            if (ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")) {
                // 根据网卡取本机配置的IP
                InetAddress inet = null;
                try {
                    inet = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
                if (inet != null) {
                    ipAddress = inet.getHostAddress();
                }
            }

        }

        // 对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if (ipAddress != null && ipAddress.length() > 15) {
            if (ipAddress.indexOf(",") > 0) {
                ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
            }
        }
        return ipAddress;
    }
	
  
}